Domain-Driven Design – warum überhaupt?
entwickler.de: Domain-Driven Design erlebt derzeit ja eine Art Renaissance. Was ist aus deiner Sicht das Spannende daran?
Golo Roden: Die Entwicklung von Software ist kein Selbstzweck. Stattdessen wird Software entwickelt, um fachliche Probleme aus der realen Welt zu lösen. Sie soll das Leben in der Regel einfacher, komfortabler und sicherer machen. Dieser Antrieb tritt in dem technologiegetriebenen Alltag der meisten Entwickler aber allzu häufig in den Hintergrund. Wir verbringen viel Zeit mit der Diskussion um die zu verwendenden Werkzeuge, sprechen aber kaum über die Fachlichkeit.
Das führt zwangsläufig zu Missverständnissen zwischen Entwicklern und Fachexperten. Langfristig macht sich das dann derart bemerkbar, dass die falsche Lösung für ein Problem entwickelt wird. Das fehlende Verständnis zwischen Technologen und Fachexperten ist also einer der primären Gründe, warum Softwareentwicklung länger dauert, fehleranfälliger und kostenintensiver ist als notwendig.
Das grundlegende Problem ist das mangelnde interdisziplinäre Verständnis in Bezug auf die Fachlichkeit.
Die Schuld dafür kann man aber nur bedingt den Entwicklern geben, denn auch die Fachexperten haben nie gelernt, interdisziplinär zu kommunizieren. Da das gleichermaßen auch für alle anderen Beteiligten gilt – unter anderem Designer, Datenbankexperten und Marketer –, tragen alle ihren Teil zu der prekären Situation bei. Letztlich ist das ein Mangel unserer spezialisierten Ausbildung, die den Blick über den Tellerrand kaum wertschätzt und ihn daher leider vermeidet.
Das grundlegende Problem ist also das mangelnde interdisziplinäre Verständnis in Bezug auf die Fachlichkeit. Will man die Effizienz von Softwareentwicklung verbessern, muss man deshalb an dieser Stelle ansetzen. Das bedeutet zugleich allerdings auch, dass dabei kein Framework helfen kann. Es spielt keine Rolle, ob React oder Angular verwendet wird, ob Node.js oder .NET. Stattdessen gilt: Wer einander nicht versteht, muss zunächst ein gemeinsames Verständnis und eine gemeinsame Sprache entwickeln.
Das zu ändern ist die Intention von Domain-Driven Design. DDD ist eine Methodik, die das gemeinsame und interdisziplinäre Modellieren eines fachlichen Problems in den Vordergrund rückt, wobei von allen Beteiligten ein gemeinsames Verständnis und eine einheitliche Sprache erarbeitet wird. Dieses strukturierte Modell lässt sich anschließend einfacher in Software umsetzen. In einem gewissen Sinn führt DDD auf dem Weg in kürzerer Zeit zu besserer Software.
Was verführerisch klingt, ist aber so einfach nicht. Da interdisziplinäres Verständnis erforderlich ist, müssen alle Beteiligten ihre Komfortzone verlassen und an ihrer Bereitschaft zu Kommunikation und Empathie arbeiten. Überwindet man die initialen Hürden, ergibt sich eine viel intensivere und effizientere Art der Zusammenarbeit. Wer einmal erlebt hat, was ein gut funktionierendes interdisziplinäres Team leisten kann, das sich im wahrsten Sinn des Wortes versteht, will dies nicht mehr missen.
entwickler.de: Domain-Driven Design wurde ja schon 2003 von Eric Evans und anderen etabliert. Weshalb hat DDD gerade jetzt wieder so Fahrt aufgenommen?
Golo Roden: In den vergangenen zehn Jahren hat sich nicht nur die Softwareentwicklung an sich verändert, sondern auch die Art von Software, die entwickelt wird. Beispielsweise spielt die nahtlose Integration von Hard- und Software für viele Produkte inzwischen eine relevante Rolle, nicht zuletzt auch bedingt durch die sich verändernden Anforderungen im Rahmen von Industrie 4.0 und dem Internet der Dinge (IoT).
Allein schon das Verbinden von Hard- und Software erfordert interdisziplinäres Denken. Fügt man dann noch die typischen neuartigen Geschäftsmodelle hinzu, werden zusätzlich weitere Disziplinen benötigt, die nicht der IT angehören. Spannend sind in der Hinsicht auch Mashups, die verschiedene Anwendungen integrieren und auf die Art unterschiedliche Fachlichkeiten verbinden.
DDD macht fachliche Komplexität greifbar.
Auch der Aufwind, den die künstliche Intelligenz derzeit erfährt, fordert interdisziplinäre Teams. Entwickler können neuronale Netze zwar entwickeln und konfigurieren, ohne einen fachlich versierten Datenexperten ist es aber schier unmöglich, das System auf sinnvolle Art zu trainieren. Dazu benötigt man ein fundiertes Verständnis der jeweiligen Fachdomäne, das sich ein Entwickler nicht aus dem Stegreif aneignen kann.
Das alles erfordert aber neue Wege der Zusammenarbeit, bei der die Fachlichkeit als verbindendes Element in den Vordergrund rückt. Deshalb wird in zunehmendem Maße auf DDD als Methodik zurückgegriffen, die Teams unterstützen kann, die Herausforderungen in den Griff zu bekommen. Glücklicherweise wurde das Rad an der Stelle einmal nicht neu erfunden, sondern auf eine bewährte Vorgehensweise zurückgegriffen.
Und selbst wer nichts mit Industrie 4.0, dem Internet der Dinge und künstlicher Intelligenz zu tun hat, trifft zumindest auf eine immer stärker zunehmende fachliche Komplexität, die es zu beherrschen gilt. Auch das ist ein guter Grund für die Wiederkehr: DDD macht fachliche Komplexität greifbar.
Domain-Driven Design, Event-Sourcing und CQRS
entwickler.de: Zwei weitere Architekturtrends sind momentan Event-Sourcing und CQRS. Welchen Zusammenhang gibt es zwischen diesen beiden und der Idee des Domain-Driven Design?
Golo Roden: Es gibt keinen inhärenten Zusammenhang zwischen DDD, Event-Sourcing und CQRS. Um das begreifen zu können, muss man zunächst verstehen, was es mit Event-Sourcing und CQRS überhaupt auf sich hat.
Event-Sourcing ist ein Ansatz zum Speichern von Daten, bei dem nicht der Jetzt-Zustand gespeichert wird, sondern die Veränderungen, die zum jetzigen Zustand geführt haben. Eine Versionsverwaltung wie Git arbeitet zum Beispiel auf diese Weise, aber auch Banken verwenden das Vorgehen, um die Transaktionen für ein Konto zu speichern, aus denen sich der aktuelle Kontostand jederzeit berechnen lässt. Event-Sourcing ist also eine Alternative zu der klassischen relationalen Datenhaltung.
DDD, Event-Sourcing und CQRS sind zwar nicht zwingend miteinander verbunden, ergänzen sich aber gegenseitig ausgezeichnet.
CQRS hingegen ist ein Architekturmuster, das die Trennung der Schreib- und der Leseseite einer Anwendung propagiert, um beide Seiten jeweils besser anpassen und individuell skalieren zu können. Dazu unterscheidet CQRS die Commands von den Queries, wobei die ersten dem Verändern des Zustands dienen, die zweiten dem Auslesen des Zustands. Trennt man die beiden Seiten, erfordert das aber eine Synchronisation, was häufig auf der Basis von Events erfolgt.
Vergleicht man DDD, Event-Sourcing und CQRS, wird klar, dass man jedes der drei Konzepte einzeln anwenden kann, ohne die jeweils anderen berücksichtigen zu müssen. Man kann ein fachliches Problem durchaus mit DDD modellieren, das Modell aber ohne Event-Sourcing und CQRS implementieren. Ebenso lässt sich Event-Sourcing zum Sammeln von Daten einsetzen, ohne zuvor ein Modell mit DDD zu entwickeln, oder CQRS zu verwenden. Und selbstverständlich ist CQRS ein gangbarer Ansatz für die Architektur einer Anwendung, auch wenn man nicht mit DDD oder Event-Sourcing arbeitet.
Trotzdem haben die drei Konzepte etwas gemeinsam, und das ist auch der Grund, warum sie regelmäßig im Verbund genannt werden. Diese Gemeinsamkeit sind die fachlichen Events. In DDD beschreiben sie Ereignisse in der Fachdomäne, in Event-Sourcing stellen sie die Basis der Persistenz dar und in CQRS dienen sie der Synchronisation von Schreib- und Leseseite.
Zusammenfassend kann man daher festhalten, dass DDD, Event-Sourcing und CQRS zwar nicht zwingend miteinander verbunden sind, sich aber gegenseitig ausgezeichnet ergänzen. Daher bietet es sich durchaus an, den gemeinsamen Einsatz der drei Konzepte in einer Entwicklung zu erwägen.
entwickler.de: Kommen wir mal zur Praxis: Wie kann man Ideen aus Event-Sourcing, CQRS und Domain-Driven Design in einer Webanwendung umsetzen? Welche Tools und Frameworks helfen dabei?
Golo Roden: Wie schon erwähnt, kann es zumindest für DDD kein Framework geben, weil ein technisches Framework niemals eine Lösung für ein fachliches Problem liefern kann. Trotzdem forciert DDD auf sprachlicher Ebene eine strukturierte Form. Man kann die Struktur beispielsweise eines Commands oder eines Events festlegen, ohne Aussagen oder Einschränkungen zu dessen Semantik zu machen. Die einheitliche Struktur ermöglicht es aber, Commands und Events zu verknüpfen.
Das heißt, die grundlegenden Bausteine von DDD lassen sich durchaus generisch in Code implementieren. Das erfolgt aber auf der Metaebene, im Prinzip so wie bei einem Compiler, der Klassen und Funktionen auf der Metaebene implementiert, unabhängig von deren späterer tatsächlicher Semantik. Ein Framework kann also die von DDD vorgeschlagene Struktur aufgreifen, was es einfacher macht, das auf Basis von DDD entworfene Modell zu implementieren.
Event-Sourcing und CQRS stellen im Gegensatz zu DDD technische Konzepte dar, weshalb sie ohne Weiteres generisch implementiert werden können.
Event-Sourcing und CQRS stellen im Gegensatz zu DDD technische Konzepte dar, weshalb sie ohne Weiteres generisch implementiert werden können. Ein Framework könnte also diese beiden Konzepte aufgreifen und, wenn es sich an die Struktur von DDD hält, dem Entwickler an der Stelle entgegenkommen.
Ein solches Framework haben wir bei the native web mit dem wolkenkit entwickelt. Es ist ein Open-Source-Framework für JavaScript und Node.js, das auf CQRS und Event-Sourcing basiert und hervorragend mit DDD harmoniert. Auf dem Weg ermöglicht das wolkenkit, sich auf das zu konzentrieren, was wirklich wichtig ist, nämlich fachliche Probleme aus der realen Welt zu lösen.
Ist das Modell auf Basis von DDD einmal entworfen, ergänzt wolkenkit die fehlenden Bestandteile für eine fertige Anwendung, unter anderem eine HTTP/2- und eine Websocket-API, JWT-basierte Authentifizierung, Autorisierung und Persistenz, und das alles wie gesagt auf der Basis von CQRS und Event-Sourcing. Der fachliche Code bleibt auf die Art getrennt von technischem Code, was dem Verständnis und der Wartbarkeit äußerst zuträglich ist.
Will man eine Anwendung auf der Basis von CQRS und Event-Sourcing ohne ein Framework wie wolkenkit von Grund auf entwickeln, ist das natürlich möglich. Allerdings befasst man sich dann zu einem Großteil der Zeit wieder mit technischen Problemen und nicht mit der eigentlich relevanten Fachlichkeit.
Microservices und React
entwickler.de: Im Zusammenhang mit Domain-Driven Design kommt immer wieder auch der Begriff Microservices vor. Wo liegen die Unterschiede zwischen dem von dir soeben beschriebenen Ansatz und der Idee der Microservices?
Golo Roden: Microservices sind kleine autonome Dienste, die auf eine einzelne Aufgabe spezialisiert sind. Das ermöglicht es, eine Anwendung zunächst in ihre Bestandteile zu zerlegen, diese autark zu entwickeln und das Gesamtproblem nachher über das Zusammenspiel vieler kleiner Services zu lösen. Die Idee ist also letztlich nichts anderes als SOA mit neuem Namen.
Die Idee der Microservices ist letztlich nichts anderes als SOA mit neuem Namen.
Zerlegt man eine Anwendung in einzelne Services, wirft das notgedrungen die Frage auf, wo in der Anwendung man die Schnitte ansetzt. Um die Entwicklung der einzelnen Dienste gut parallelisieren zu können, empfiehlt es sich, die Anwendung nach fachlichen und nicht nach technischen Kriterien zu schneiden. Dazu muss man aber wiederum die Fachlichkeit verstanden haben und fachliche Grenzen ziehen können. Genau das wird mit DDD erreicht, weshalb Microservices gerne in Verbindung mit DDD eingesetzt werden.
Letztlich sind Microservices aber lediglich ein technisches Implementierungsdetail. Ob Microservices wirklich der passende Ansatz sind, oder ob man mit einem Monolithen oder einer FaaS-Architektur besser fährt, sind technische Fragen, die einen Fachexperten nicht interessieren dürften. Natürlich sind die Fragen wichtig, aber es wäre ein Fehler, daraus einen direkten Zusammenhang zwischen Microservices und DDD zu schließen. Die beiden Konzepte passen nur zufällig gut zueinander, weil die Fachlichkeit für beide eine wichtige Rolle spielt – wenn auch aus unterschiedlichen Gründen.
Ein interessanter Gedanke ist übrigens, dass ein Framework wie wolkenkit für die gleiche fachliche Modellierung verschiedene technische Implementierungen verwenden könnte. Je nach Bedarf könnte man die Anwendung mit Microservices, auf Basis von FaaS oder als Monolith ausführen, ohne den Code anpassen zu müssen, da dieser lediglich die Fachlichkeit beschreibt.
entwickler.de: Auf den JS Days hältst du einen Workshop über React. Inwiefern lassen sich die genannten Konzepte – Domain-Driven Design, CQRS, Microservices, Event-Sourcing – mit React umsetzen?
Golo Roden: DDD ist unabhängig von einer konkreten Technologie, insofern kann man React selbstverständlich verwenden, um eine auf Basis von DDD entworfene Modellierung zu implementieren.
Event-Sourcing und CQRS hingegen lassen sich direkt mit React umsetzen, und tatsächlich geschieht das auch schon regelmäßig. Zustandscontainer wie Redux basieren auf genau diesen Konzepten, indem sie das Ändern des Zustands vom Auslesen desselben trennen und semantische Anweisungen als Auslöser für Veränderung verwenden. Schaut man sich modernen React-Code an, fällt auf, dass die klassischen CRUD-Verben dort kaum noch zu finden sind. Der Schwerpunkt hat sich vom Verarbeiten von Daten auf das Ausführen von Prozessen verlagert. In diesem Sinn könnte man sagen, dass wolkenkit einer Art Redux für den Server entspricht.
entwickler.de: Wenn wir gerade bei React sind: Was fehlt dir momentan noch in dem Framework, das du dir in einer der nächsten Versionen wünschen würdest?
Golo Roden: Im August 2017 habe ich auf eine ähnliche Frage geantwortet, dass ich mir mehr Dokumentation wünschen würde, die den Bogen von React zu funktionaler Programmierung schlägt und die theoretischen Konzepte hinter React fundiert und detailliert erläutert, unter anderem die Idee der Unveränderlichkeit und den Ansatz des unidirektionalen Datenflusses. Daran hat sich prinzipiell nichts geändert.
Was mir an React immer schon gut gefallen hat, ist die Tatsache, dass es sehr eng mit JavaScript integriert ist.
Was mir an React immer schon ausgesprochen gut gefallen hat, ist die Tatsache, dass es sehr eng und sehr gut mit JavaScript integriert ist. Bessere JavaScript-Kenntnisse führen automatisch zu besseren React-Kenntnissen und umgekehrt. Betrachtet man React vor dem Hintergrund von DDD, Event-Sourcing und CQRS, gilt etwas Ähnliches. Wer die drei Konzepte verstanden hat, dem fällt es leichter, eine gute Frontend-Architektur mit React aufzubauen.
Abschließend sei deshalb an dieser Stelle noch unsere Broschüre zu DDD, Event-Sourcing und CQRS empfohlen, die man kostenlos als PDF herunterladen kann.
entwickler.de: Vielen Dank für dieses Interview!
Das Interview führte Hartmut Schlosser